package com.le.tester.imooc.oldfairy.coding.proxy;

import com.le.tester.imooc.oldfairy.basic.Try;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * createTime：2023/5/18 15:37
 * description：反射，代理，切面，rpc使用base
 */
public interface Aspect {

    void before();

    void after();

    //切面代理
    static <T> T getProxy(Class<T> cls, String... aspects) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        List<Try<Aspect>> aspectList = Arrays.stream(aspects)
                .map(name -> Try.ofFailureAble(() -> {
                    Class<?> clazz = Class.forName(name);
                    return (Aspect) clazz.getConstructor().newInstance();
                }))
                .filter(Try::isSuccess)
                .collect(Collectors.toList());

        T instance = cls.getConstructor().newInstance();

        return (T) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                for (Try<Aspect> aspect : aspectList) {
                    aspect.get().before();
                }
                Object result = method.invoke(instance);

                for (Try<Aspect> aspect : aspectList) {
                    aspect.get().after();
                }
                return result;
            }
        });
    }
}
